package py.com.alfa.escriba.gui.session;

import java.io.IOException;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import py.com.alfa.escriba.gui.config.ConfigLocator;
import py.com.alfa.escriba.gui.config.EscribaGUIApplicationContextProvider;
import py.com.alfa.escriba.gui.config.EscribaGUIConfig;
import py.com.alfa.escriba.gui.controller.view.ViewManager;
import py.com.alfa.escriba.gui.dto.ServicioDTO;
import py.com.alfa.escriba.gui.dto.UserResponseDTO;
import py.com.alfa.escriba.gui.rest.services.AdminService;
import py.com.alfa.escriba.gui.rest.services.LoginService;
import py.com.alfa.escriba.gui.services.Services;
import py.com.alfa.escriba.gui.utils.DateUtils;


public class EscribaGUIRealm extends AuthorizingRealm {
	private Logger log = LoggerFactory.getLogger(getClass());
	private String username = null;
	private String password = null;
	private ApplicationContext ctx;
	private EscribaGUIConfig config;
	private SystemInfo systemInfo;

	public EscribaGUIRealm() {
		log.info("\n==============\nBuilding Realm\n==============\n");
		ctx = EscribaGUIApplicationContextProvider.getContext();
		ConfigLocator configLocator = (ConfigLocator) ctx.getBean(Services.CONFIG_LOCATOR);
		config = configLocator.getConfig();
	}

	private void buildWrapper() {
		systemInfo.setAuthenticated(false);
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) {
		log.info("\n==============\nAuthorizing\n==============\n");
		SimpleAuthorizationInfo info = null;
		try {
			systemInfo = (SystemInfo) ctx.getBean(Services.SYSTEM_INFO);
			info = new SimpleAuthorizationInfo(systemInfo.getRoles());
			info.setStringPermissions(systemInfo.getRoles());
			
			log.info("ROLES: {} - Permissions: {}", info.getStringPermissions(), info.getStringPermissions());
			ViewManager viewManager = (ViewManager) ctx.getBean(Services.VIEW_MANAGER);
			viewManager.mapPermissions(info.getStringPermissions());
			viewManager.printPermissions();
		} catch (Exception e) {
			log.error("LOGIN: {}", e.getMessage());
			throw new AuthorizationException(e.getMessage());
		}
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException {
		log.info("\n==============\nAuthenticating\n==============\n");
		LoginService login=(LoginService)ctx.getBean(Services.LOGIN);
		AdminService admin= ctx.getBean(Services.ADMIN, AdminService.class);
		UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
		systemInfo = (SystemInfo) ctx.getBean(Services.SYSTEM_INFO);
		this.username = userPassToken.getUsername();
		char[] pass = userPassToken.getPassword();
		StringBuffer sb = new StringBuffer();

		buildWrapper();
		if (username == null) {
			log.debug("Username is null.");
			return null;
		}		
		for (char c : pass) {
			sb.append(c);
		}

		this.password = sb.toString();
		log.info("Username: {} ", username);
        UserResponseDTO resp = null;		
		try {
			resp = login.validUser(username, password);
			log.info("User: {} ", resp);
			systemInfo.setAuthenticated(true);
			systemInfo.setNombreUsuario(resp.getUser().getName());
			systemInfo.setIdUser(resp.getUser().getId());
			systemInfo.setUserName(username);
			systemInfo.setIdEscribano(resp.getUser().getIdEscribano());
			if(systemInfo.getIdEscribano() != null){
				systemInfo.setEscribano(admin.obtenerEscribano(systemInfo.getIdEscribano()));
				log.info("Escribano: {} ", systemInfo.getEscribano());
			}
			Set<String> roles = new LinkedHashSet<String>();
			for (ServicioDTO srv : resp.getSrvs()) {
			  	roles.add(srv.getCodFunc().trim());
//				roles.add(srv.getDescripcion());
			  	log.info("\n==============ROLES {}==============\n", srv.getCodFunc());
			}
			systemInfo.setRoles(roles);
			
		} catch (IOException e) {
			log.error("LOGIN: {}", e.getMessage());
			throw new AuthenticationException(e.getMessage());
		}

		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
		systemInfo.setCalendar(Calendar.getInstance());
		systemInfo.setFechaHora(DateUtils.getCurrentWithTime());
		return info;
	}

}
